package com.societyGames.codeAlong.state.codeExercise.view
{
import com.societyGames.flashForms.SingleItemContainer;

import flash.events.Event;
import flash.geom.Rectangle;

/**
 * Centers and scales the item, maintaining its aspect ratio.
 * Handles non zero origin cases.
 */
public class ModuleContainer extends SingleItemContainer
{
  private var _desiredWidth:Number;
  private var _desiredHeight:Number;

  public override function set width(value:Number):void
  {
    this._desiredWidth = value;
    recalculate();
  }

  public override function set height(value:Number):void
  {
    this._desiredHeight = value;
    recalculate();
  }

  protected override function childSizeChangedHandler(event:Event):void
  {
    recalculate();
  }

  /*private function calculateAspectRatioScaleDownOnly():Number
   {
   var scale:Number;
   if (this.item.width > this._desiredWidth || this.item.height > this._desiredHeight)
   {
   scale = Math.min(
   this._desiredWidth / this._item.width,
   this._desiredHeight / this._item.height
   );
   }
   else
   {
   scale = 1;
   }
   return scale;
   }*/

  private function calculateAspectRatioScale():Number
  {
    var scale:Number = Math.min(
                    this._desiredWidth / this._item.width,
                    this._desiredHeight / this._item.height
    );

    return isNaN(scale) || !isFinite(scale) ? 1 : scale;
  }

  //From "Hacker's Delight", Henry S. Warren Jr.
  private static function calculateLowerPowerOfTwo(x:uint):uint
  {
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);
    return x - (x >> 1);
  }

  private function recalculate():void
  {
    if (this._item != null)
    {
      this._item.scaleX = 1;
      this._item.scaleY = 1;
      var scale:Number = calculateAspectRatioScale();
      if (scale > 1)
      {
        scale = calculateLowerPowerOfTwo(uint(scale));
      }
      this._item.scaleX = scale;
      this._item.scaleY = scale;

      //Center the 0,0 first.
      this._item.x = this._desiredWidth * 0.5;
      this._item.y = this._desiredHeight * 0.5;
      //Then shift it over.
      var bounds:Rectangle = this._item.getBounds(this);
      this._item.x += this._item.x - (bounds.left + 0.5 * bounds.width);
      this._item.y += this._item.y - (bounds.top + 0.5 * bounds.height);
    }
  }
}
}